package org.gw.ylc.base.data;

import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.EntityMode;
import org.hibernate.Transaction;
import org.hibernate.type.Type;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.Iterator;
import java.util.Map;

public class HibernateInterceptor extends EmptyInterceptor {

	private static final long serialVersionUID = 1L;

	@Override
	public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
			throws CallbackException {
		EntityPermission permission = PermissionContext.getInstance().getPermission(entity.getClass().getName());
		if (permission != null) {
			Map<String, PropertyAccess> accessMap = permission.getAccessMap();
			for (int i = 0; i < propertyNames.length; i++) {
				String prop = propertyNames[i];
				PropertyAccess access = accessMap.get(prop);
				boolean can = true;
				if (access != null && access.isReadable()) {
					if (StringUtils.hasText(access.getAvailableExpr())) {
						Object eval = PermissionContext.eval(access.getAvailableExpr(), "entity", entity);
						if (!Boolean.TRUE.equals(eval)) {
							can = false;
						}
					}
				} else {
					can = false;
				}
				if (!can) {
					state[i] = null;
				}
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) throws CallbackException {
		EntityPermission permission = PermissionContext.getInstance().getPermission(entity.getClass().getName());
		if (permission != null) {
			Map<String, PropertyAccess> accessMap = permission.getAccessMap();
			for (int i = 0; i < propertyNames.length; i++) {
				String prop = propertyNames[i];
				PropertyAccess access = accessMap.get(prop);
				boolean can = true;
				if (access != null && access.isWritable()) {
					if (StringUtils.hasText(access.getAvailableExpr())) {
						Object eval = PermissionContext.eval(access.getAvailableExpr(), "entity", entity);
						if (!Boolean.TRUE.equals(eval)) {
							can = false;
						}
					}
				} else {
					can = false;
				}
				if (!can) {
					currentState[i] = previousState[i];
				}
			}
			return true;
		}
		return false;
	}

	@Override
	public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
			throws CallbackException {
		EntityPermission permission = PermissionContext.getInstance().getPermission(entity.getClass().getName());
		if (permission != null) {
			Map<String, PropertyAccess> accessMap = permission.getAccessMap();
			for (int i = 0; i < propertyNames.length; i++) {
				String prop = propertyNames[i];
				PropertyAccess access = accessMap.get(prop);
				boolean can = true;
				if (access != null && access.isWritable()) {
					if (StringUtils.hasText(access.getAvailableExpr())) {
						Object eval = PermissionContext.eval(access.getAvailableExpr(), "entity", entity);
						if (!Boolean.TRUE.equals(eval)) {
							can = false;
						}
					}
				} else {
					can = false;
				}
				if (!can) {
					state[i] = null;
					if (StringUtils.hasText(access.getDefaultValueExpr())) {
						Object eval = PermissionContext.eval(access.getDefaultValueExpr(), "entity", entity);
						state[i] = eval;
					}
				}
			}
			return true;
		}
		return false;
	}

	@Override
	public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
			throws CallbackException {

	}

	@Override
	public void onCollectionRecreate(Object collection, Serializable key) throws CallbackException {

	}

	@Override
	public void onCollectionRemove(Object collection, Serializable key) throws CallbackException {
		// TODO Auto-generated method stub

	}

	@Override
	public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
		// TODO Auto-generated method stub

	}

	@Override
	public void preFlush(Iterator entities) throws CallbackException {
		// TODO Auto-generated method stub

	}

	@Override
	public void postFlush(Iterator entities) throws CallbackException {
		// TODO Auto-generated method stub

	}

	@Override
	public Boolean isTransient(Object entity) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
			String[] propertyNames, Type[] types) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object instantiate(String entityName, EntityMode entityMode, Serializable id) throws CallbackException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getEntityName(Object object) throws CallbackException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Object getEntity(String entityName, Serializable id) throws CallbackException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void afterTransactionBegin(Transaction tx) {
		// TODO Auto-generated method stub

	}

	@Override
	public void beforeTransactionCompletion(Transaction tx) {
		// TODO Auto-generated method stub

	}

	@Override
	public void afterTransactionCompletion(Transaction tx) {
		// TODO Auto-generated method stub

	}

	@Override
	public String onPrepareStatement(String sql) {
		// TODO Auto-generated method stub
		return null;
	}

}
